﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Cms.Application.Admin.Views;
using Cms.Application.IO;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;
using iLib.Web.UI;

namespace Cms.Application.Admin.Presenters
{
    public class EditContentPresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly IEditContentView _view;
        public IDiskAccess DiskAccess;

        public EditContentPresenter(IEditContentView view)
            : this(view, new RepositoryFactory())
        {
            DiskAccess = new DiskAccess();
        }
        
        public EditContentPresenter(IEditContentView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!_administrator.HasPermission.EditContent)
                _view.RedirectToPermissionDeniedPage();
        }

        public void Initialize()
        {
            // Initialize to empty lists as a fallback mechanism for categories and groups
            IList<Category> categories = new List<Category>();
            IList<AdministratorGroup> allowedAdministratorGroups = new List<AdministratorGroup>();
            IList<AdministratorGroup> deniedAdministratorGroups = new List<AdministratorGroup>();
            IList<UserGroup> requiredUserGroups = new List<UserGroup>();
            IList<UserGroup> deselectedUserGroups = new List<UserGroup>();
            // Fetch version, if any
            ContentTranslationVersion ctv = ContentRepository.GetContentTranslationVersion(_view.VersionID);
            if (_view.ContentID != -1)
            {
                // Edit freestanding content or new content
                Content content = ContentRepository.GetContent(_view.ContentID);
                if (ctv != null)
                {
                    _view.Content = ctv.Html;
                    _view.ContentTitle = ctv.Title;
                }
                if (content != null)
                {
                    _view.SetHeaderContentDescription(content.Name);
                    _view.Name = content.Name;
                    _view.SortKey = content.SortKey;
                    _view.StartPublishing = content.StartPublishing;
                    _view.EndPublishing = content.EndPublishing;
                    categories = content.Categories;
                    allowedAdministratorGroups = content.AllowedAdministratorGroups;
                    deniedAdministratorGroups = content.DeniedAdministratorGroups;
                    requiredUserGroups = content.RequiredUserGroups;
                    deselectedUserGroups = content.DeselectedUserGroups;
                }
                else
                {
                    // New content
                    _view.SetHeaderContentDescription(null);
                    Category selectedCategory = CategoryRepository.GetCategory(_view.SelectedCategoryID);
                    if (selectedCategory != null)
                    {
                        categories.Add(selectedCategory);
                        if (selectedCategory.DefaultSortKey != DefaultCategorySortKey.None)
                        {
                            switch (selectedCategory.DefaultSortKey)
                            {
                                case DefaultCategorySortKey.DateTime:
                                    _view.SortKey = DateTime.Now.ToString("yyyy-MM-dd");
                                    break;
                            }
                        }
                    }
                }
            }
            else
            {
                ContentSetContainer container = null;
                if (_view.PageID > 0)
                {
                    Page page = PageRepository.GetPage(_view.PageID);
                    if (!string.IsNullOrEmpty(page.Name))
                        _view.SetHeaderContentDescription(page.Name + ", " + _view.AreaID);
                    else
                        _view.SetHeaderContentDescription(page.Filename + ", " + _view.AreaID);
                    container = page;
                }
                else if (_view.DetailTemplateID > 0)
                {
                    container = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
                    _view.SetHeaderContentDescription(container.Name + ", " + _view.AreaID);
                }
                else if (_view.MasterTemplateID > 0)
                {
                    container = SiteRepository.GetMasterTemplate(_view.MasterTemplateID);
                    _view.SetHeaderContentDescription(container.Name + ", " + _view.AreaID);
                }
                if (container != null)
                {
                    if (ctv != null)
                    {
                        _view.Content = container.GetContentHtml(_view.AreaID, _view.LocaleID, ctv.Timestamp);
                        _view.ContentTitle = container.GetContentTitle(_view.AreaID, _view.LocaleID, ctv.Timestamp);
                        _view.Name = ctv.Translation.Content.Name;
                        _view.SortKey = ctv.Translation.Content.SortKey;
                    }
                    else
                    {
                        _view.Content = container.GetPublishedContentHtml(_view.AreaID, _view.LocaleID);
                        _view.ContentTitle = container.GetPublishedContentTitle(_view.AreaID, _view.LocaleID);
                        _view.Name = container.Name + ", " + _view.AreaID;
                    }
                    Content content = container.GetContent(_view.AreaID);
                    if (content != null)
                    {
                        categories = content.Categories;
                        allowedAdministratorGroups = content.AllowedAdministratorGroups;
                        deniedAdministratorGroups = content.DeniedAdministratorGroups;
                        requiredUserGroups = content.RequiredUserGroups;
                        deselectedUserGroups = content.DeselectedUserGroups;
                        _view.StartPublishing = content.StartPublishing;
                        _view.EndPublishing = content.EndPublishing;
                    }
                }
            }
            _view.SetCategories(_administrator.CurrentSite.GetRootCategories(), new List<Category>(), categories);
            _view.SetAllowedAdministratorGroups(AdministratorRepository.GetCustomGroups(), new List<AdministratorGroup>(), allowedAdministratorGroups);
            _view.SetDeniedAdministratorGroups(AdministratorRepository.GetCustomGroups(), new List<AdministratorGroup>(), deniedAdministratorGroups);
            _view.SetRequiredUserGroups(UserRepository.GetUserGroups(), new List<UserGroup>(), requiredUserGroups, deselectedUserGroups);
        }

        public string GetStylesheets(string editorBodyWidth)
        {
            string width = string.IsNullOrEmpty(editorBodyWidth) ? "" : "width: " + editorBodyWidth + "px;";
            DiskAccess.CreateTextFile("Admin\\Resources\\Temp\\" + _administrator.ID + "\\EditorBodyWidth.css", "body { " + width + " }");
            MasterTemplate masterTemplate = SiteRepository.GetMasterTemplate(_view.MasterTemplateID);
            string files = "";
            foreach (Stylesheet stylesheet in masterTemplate.GetStylesheets())
            {
                if (files.Length > 0)
                    files += ",";
                files += Url.VirtualPath + "__System/Stylesheets/" + stylesheet.ID + ".css?v=" + stylesheet.SourceCode.CurrentVersion.Timestamp;
            }
            files += "," + Url.VirtualPath + "Admin/Resources/Temp/" + _administrator.ID + "/EditorBodyWidth.css?v=" + DateTime.Now.Ticks;
            return files;
        }

        private Content GetContent()
        {
            Content content;
            if (_view.CurrentContentID > 0)
                content = ContentRepository.GetContent(_view.CurrentContentID);
            else if (_view.ContentID != -1)
            {
                if (_view.ContentID < 0)
                {
                    content = new Content
                                  {
                                      CreatedBy = _administrator,
                                      Site = _administrator.CurrentSite,
                                      Name = _view.Name
                                  };
                    content.Site.Content.Add(content);
                    SiteRepository.SaveSite(content.Site);
                }
                else
                {
                    content = ContentRepository.GetContent(_view.ContentID);
                }
            }
            else
            {
                ContentSetContainer container = GetContainer();
                content = container.GetContent(_view.AreaID);
                if (content == null)
                {
                    content = new Content
                                  {
                                      CreatedBy = _administrator,
                                      Site = _administrator.CurrentSite,
                                      Name = _view.Name
                                  };
                    content.Site.Content.Add(content);
                    SiteRepository.SaveSite(content.Site);
                    container.AddContentLink(_view.AreaID, content);
                    SiteRepository.SaveSite(content.Site);
                }
            }
            _view.CurrentContentID = content.ID;
            return content;
        }
        
        private ContentSetContainer GetContainer()
        {
            ContentSetContainer container = null;
            if (_view.PageID > 0)
                container = PageRepository.GetPage(_view.PageID);
            else if (_view.DetailTemplateID > 0)
                container = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
            else if (_view.MasterTemplateID > 0)
                container = SiteRepository.GetMasterTemplate(_view.MasterTemplateID);
            return container;
        }

        public int Save()
        {
            if (_view.Name.Trim() == "")
                AddValidationError(GetText(_view, "NoNameError"));
            if (!IsValid)
                return -1;
            Content content = GetContent();
            ContentTranslationVersion ctv = null;
            Locale locale = LocaleRepository.GetLocale(_view.LocaleID);
            if (_view.CurrentTab == "content")
            {
                // Ensure that all plugins have pluginid as their first attribute. This is necessary for the search result control.
                string html = Regex.Replace(_view.Content, @"(<frediumplugin)(\s.*)(\spluginid="".+?"")(.*?>)",
                                            "$1$3$2$4");
                // Also ensure that any fredium page breaks have their wrapping p tag removed
                html = html.Replace("<p><!-- pagebreak --></p>", "<!-- pagebreak -->");
                ctv = content.AddVersion(locale, DateTime.Now.Ticks, html, _view.ContentTitle, _administrator);
                foreach (ContentSetContainer container in content.GetContainers())
                    container.GetContentSet(locale).TranslationVersions.Add(ctv);
            }
            content.Name = _view.Name;
            content.SortKey = _view.SortKey;
            content.StartPublishing = _view.StartPublishing;
            content.EndPublishing = _view.EndPublishing;
            foreach (Category category in content.Categories)
                category.Content.Remove(content);
            content.Categories.Clear();
            foreach (Category category in _view.GetSelectedCategories())
            {
                content.Categories.Add(category);
                category.Content.Add(content);
            }
            foreach (AdministratorGroup group in content.AllowedAdministratorGroups)
                group.AllowedContent.Remove(content);
            content.AllowedAdministratorGroups.Clear();
            foreach (AdministratorGroup group in _view.GetSelectedAllowedAdministratorGroups())
            {
                content.AllowedAdministratorGroups.Add(group);
                group.AllowedContent.Add(content);
            }
            foreach (AdministratorGroup group in content.DeniedAdministratorGroups)
                group.DeniedContent.Remove(content);
            content.DeniedAdministratorGroups.Clear();
            foreach (AdministratorGroup group in _view.GetSelectedDeniedAdministratorGroups())
            {
                content.DeniedAdministratorGroups.Add(group);
                group.DeniedContent.Add(content);
            }
            foreach (UserGroup group in content.RequiredUserGroups)
                group.SelectedContent.Remove(content);
            content.RequiredUserGroups.Clear();
            foreach (UserGroup group in _view.GetSelectedRequiredUserGroups())
            {
                content.RequiredUserGroups.Add(group);
                group.SelectedContent.Add(content);
            }
            SiteRepository.SaveSite(_administrator.CurrentSite);
            if (ctv != null && _view.CurrentTab == "content")
                return ctv.ID;
            return _view.VersionID;
        }
        
        public bool IsInCategory(Category category)
        {
            Content content = null;
            if (_view.CurrentContentID > 0)
                content = ContentRepository.GetContent(_view.CurrentContentID);
            else if (_view.ContentID != -1)
                content = ContentRepository.GetContent(_view.ContentID);
            else
            {
                ContentSetContainer container = GetContainer();
                content = container.GetContent(_view.AreaID);
            }
            return category.ContainsContent(content);
        }
    }
}